#include "BottlingPlant.h"

BottlingPlant::BottlingPlant( Printer &prt, NameServer &nameServer, unsigned int numVendingMachines,
							  unsigned int maxShippedPerFlavour, unsigned int maxStockPerFlavour,
							  unsigned int timeBetweenShipments ) : 
myPrinter(prt), myNameServer(nameServer), myNumVendingMachines(numVendingMachines),
myMaxShippedPerFlavour(maxShippedPerFlavour), myMaxStockPerFlavour(maxStockPerFlavour),
myTimeBetweenShipments(timeBetweenShipments),
myClosingDown(false)
{
    myShipments = new unsigned int[VendingMachine::FLAVOUR_SIZE]();
    for(unsigned int i = 0; i<VendingMachine::FLAVOUR_SIZE; i++)
    {
        myShipments[i] = 0;
    }
}

BottlingPlant::~BottlingPlant()
{
	// need to clean up any allocated resources
	delete[] myShipments;
}

void BottlingPlant::main()
{
    myPrinter.print(Printer::BottlingPlant, 'S');
    Truck* truck = new Truck(myPrinter, myNameServer, *this,
                            myNumVendingMachines, myMaxStockPerFlavour);
    for(;;)
    {
        _Accept(~BottlingPlant) 
        {
            break;
        }else{
            // production run
            yield(myTimeBetweenShipments); 
            unsigned int sum = 0;
            for(unsigned int i = 0; i<VendingMachine::FLAVOUR_SIZE; i++)
            {
                myShipments[i] = Global::prng() % (myMaxShippedPerFlavour+1);
                sum += myShipments[i];
            }
            myPrinter.print(Printer::BottlingPlant, 'G', sum);
            _Accept(getShipment);
            myPrinter.print(Printer::BottlingPlant, 'P');
        }      
    }   

    myClosingDown = true;
	// Block here to make sure that truck can get the last shipment
	// and get the closing notice.
	// If we simply call delete on truck, then the Plant would be waiting
	// for the truck inside the monitor, and the truck would be blocked
	// on getShipment, and thus a deadlock
	_Accept(getShipment);

    delete truck;
    myPrinter.print(Printer::BottlingPlant, 'F');
}

bool BottlingPlant::getShipment( unsigned int cargo[] )
{
    if(myClosingDown) return true;
    for(unsigned int i=0; i<VendingMachine::FLAVOUR_SIZE; i++)
    {
        cargo[i] = myShipments[i];
    }    
    return false;
}
